package org.future.dev.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


/**
 * 读写文件
 * @author shixg
 * @date 2009-12-12 下午12:00:01
 */
public class FileUtils {
    /**
     * 以树形结构列出当前目录下的目录及文件
     * @param dir :String
     * @param level :int 当前层数
     * @param displayAll :boolean 是否显示当前目录及所有子目录中的文件及目录
     * @param deep :int 迭代深度
     */
    private static void treeWin(
            String dir,int level,
            boolean displayAll,int deep){
        int step = 4;               // 每次缩进的长度
        int len = level * step;     // 当前层需缩进的长度
        char pre_d = '+';           // 目录前导符
        char pre_f = '|';           // 文件前导符
        char ch = '-';              // 填充字符
        String filler = "";         // 填充字符串
        File file = new File(dir);
        if(file.isDirectory()){
            filler += pre_d;
        } else if(file.isFile()){
            filler += pre_f;
        }
        for(int i=0; i < step; i++){
            filler += ch;
        }
        String file_name = file.getName();
        // 格式字符串
        String format = "%" + (len+filler.length()) + "s" + "%s\n";
        // 显示当前内容
        System.out.format(format, filler,file_name);
        // 显示下级内容
        // 当 displayAll == true 时，不检查深度 deep
        // 当 displayAll == false 时，按深度 deep 进行迭代
        if(file.isDirectory() && (displayAll || (level < deep))){
            File[] fs = file.listFiles();
            for(File f : fs){     // 递归文件
                if(f.isFile()){
                    treeWin(f.getAbsolutePath(),level+1,displayAll,deep);
                }
            }
            for(File f : fs){     // 递归目录
                if(f.isDirectory()){
                    treeWin(f.getAbsolutePath(),level+1,displayAll,deep);
                }
            }
        } 
    }
    /**
     * 以树形结构列出当前目录下的目录及文件
     * @param dir :String
     * @param deep :int 迭代深度
     */
    public static void tree(String dir,int deep){
        treeWin(dir, 0, false, deep);
    }
    /**
     * 以树形结构列出当前目录下的 全部 目录及文件
     * @param dir :String
     */
    public static void treeAll(String dir){
        treeWin(dir, 0, true, -1);
    }
    /**
     * 复制文件
     * @param src :String fileName
     * @param dest :String fileName
     * @throws Exception
     */
    public static void copyFile(String src,String dest){
        File infile = new File(src);
        File outfile = new File(dest);
        if(!infile.isFile()){
            throw new RuntimeException(src + "不是一个可以使用的文件[目录或者不存在]");
        }        
        FileInputStream in = null;
        FileOutputStream out = null;
        try{
            in = new FileInputStream(infile);
            out = new FileOutputStream(outfile);
            int data = in.read();
            while(data != -1){             // 以字节形式读写文件
                out.write(data);
                data = in.read();
            }
        } catch(IOException e){
            e.printStackTrace();
        } finally{
            try{
                if(in != null){
                    in.close();
                }
                if(out != null){
                    out.flush();
                    out.close();
                }
            } catch(Exception e){
                
            }
        }
    } 
    /**
     * 删除目录
     * @param dirpath :String
     */
    public static void deleteDir(String dirpath){
        File dir = new File(dirpath);
        if(!dir.exists()){                                   // 目录不存在
            return;
        }
        if(dir.isDirectory()){                               // 如果是目录递归删除子文件
            File[] fs = dir.listFiles();
            for(File f : fs){
                deleteDir(f);
            }
        }
        dir.delete();                                        // 删除当前目录/文件
    }
    /**
     * 删除目录
     * @param dir :File
     */
    public static void deleteDir(File dir){
        if(!dir.exists()){                                   // 目录不存在
            return;
        }
        if(dir.isDirectory()){                               // 如果是目录递归删除子文件
            File[] fs = dir.listFiles();
            for(File f : fs){
                deleteDir(f);
            }
        }
        dir.delete();                                        // 删除当前目录/文件
    }
    /**
     * 返回目录 dir 及所有子目录中以 suffix 结尾的 文件
     * @param dir :String
     * @param suffix :String
     * @return List<String> fileAbsolutePath
     */
    public static List<String> getAllFiles(String dir,String suffix){
        List<String> list = new ArrayList<String>();
        File file = new File(dir);
        String filename = file.getName().toLowerCase();// 文件名转小写
        if(file.isFile() && (filename.endsWith(suffix))){
            list.add(file.getAbsolutePath());
        } else if(file.isDirectory()){
            File[] fs = file.listFiles();
            for(File f : fs){                           // 遍历当前目录
                getAllFiles(f,suffix,list);             // 递归遍历子目录
            }
        }
        return list;
    } 
    /**
     * 取出目录 dir 及所有子目录中以 suffix 结尾的 文件
     * @param file :File
     * @param suffix :String
     * @param list :List<String>
     */
    private static void getAllFiles(File file,String suffix,List<String> list){
        String filename = file.getName().toLowerCase(); // 文件名转小写
        if(file.isFile() && (filename.endsWith(suffix))){
            list.add(file.getAbsolutePath());
        } else if(file.isDirectory()){
            File[] fs = file.listFiles();
            for(File f : fs){                           // 遍历当前目录
                getAllFiles(f,suffix,list);             // 递归遍历子目录
            }
        }
    }// end
    /**
     * 返回当前目录下的所有目录及文件
     * @param dir
     * @param onlyDir 是否只包含目录而不包括文件
     * @return
     */
    public static List<String> getCurrentFiles(String dir,boolean onlyDir){
        List<String> list = new ArrayList<String>();
        File file = new File(dir);
        File[] fs = file.listFiles();
        for(File f : fs){                           // 遍历当前目录
            if(onlyDir && f.isFile()){
                continue;
            }
            list.add(f.getAbsolutePath());
        }
        return list;
    }
}
